<template>
    <div class="common-info-container full-percent" ref="workflowContainerRef">
        <div class="`forbid-select full-percent" @contextmenu.prevent>
            <DAGBoard :DataAll="DataAll" @updateDAG="updateWorkflow" @editNodeDetails="editNodeDetails"
                @focusInput="focusInput" :toolbar="toolbar" ref="workflowRef" :addNodeFunction="addNodeFunction"
                @openTask="openTask" @npc="click" :useKeyMap="useKeyMap" class="full-percent" />
            <el-dialog :title="currentNodeId ? 'Modify Workflow' : 'Add Workflow'" v-model="workflowVisible" width="80%"
                @close="close" :close-on-click-modal="false" class="dag-page-dialog" top="60px" append-to-body>
                <el-form inline :model="searchForm" class="form-item" spellcheck="false" @submit.native.prevent>
                    <el-row style="padding: 5px;">
                        <el-col :span="10" style="padding-right: 5px">
                            <el-input v-model="searchForm.jobDesc" placeholder="任务名称" clearable
                                class="input-auto-resize" @keyup.enter.native="search"></el-input>
                        </el-col>
                        <el-col :span="4" style="padding-right: 5px">
                            <el-button type="primary" @click="search" circle class="button-auto-resize"
                                :loading="bt_loading" :icon="getIcon('search')" />
                        </el-col>
                    </el-row>
                </el-form>

                <el-table border header-cell-class-name="el-table-header-cell" cell-class-name="el-table-cell"
                    :data="tableData" v-loading="tb_loading" class="table-with-pagination" highlight-current-row>
                    <el-table-column label="任务名称" prop="jobDesc" :fit="false" min-width="150" />
                    <el-table-column label="任务类型" prop="glueType" min-width="150">
                        <template #default="scope">
                            {{ getGlueType(scope.row.glueType) }}
                        </template>
                    </el-table-column>
                    <el-table-column label="下次执行时间" prop="triggerNextTime" :width="fontAutoResize.size_12.value">
                        <template #default="scope">
                            {{ scope.row.triggerNextTime > 0 ?
                                new Date(scope.row.triggerNextTime).format("YYYY-MM-DD HH:mm:ss") : "-" }}
                        </template>
                    </el-table-column>
                    <el-table-column label="备注" prop="remark" min-width="250" />
                    <el-table-column label="操作" :width="operationWidth" className="operation-column">
                        <template #default="scope">
                            <el-button @click.native.prevent="modifyJob(scope)" circle :icon="getIcon('Location')"
                                :loading="bt_loading" class="button-auto-resize" type="primary" />
                        </template>
                    </el-table-column>
                </el-table>
                <div style="height: 50px;">
                    <el-pagination background @size-change="SizeChange" @current-change="CurrentChange"
                        :current-page="currentPage" :page-sizes="page_sizes" :page-size="page_size"
                        layout="total, sizes, prev, pager, next, jumper" prev-text="<上一页" next-text="下一页>"
                        :total="total">
                    </el-pagination>
                </div>
            </el-dialog>
        </div>

        <WorkflowComponentInfo v-model="showComponentInfo" :node-info=currentComponent />
    </div>
</template>

<script setup>
import router from "@/router"
import WorkflowComponentInfo from "./workflowComponentInfo"
import { isInArray, deepCopy, getIcon } from "@/utils/tools"
import { useElMessage, useSetTableOperationWidth, useModalSize, useRequest } from "@usehook"
import DAGBoard from "@/components/dag/dagContent"
import { fontAutoResize } from "@/utils/setting"
import storeInstance from "@/pinia"

const operationWidth = useSetTableOperationWidth(1)
const props = defineProps({
    activeTab: { type: String, default: '' },
    saveButton: { default: true, type: Boolean, },
})

let currentComponent = $ref({ name: "", group: "" })

const useKeyMap = $computed(() => {
    return props.activeTab === 'fix-common'
})

const route = router.currentRoute.value
let showComponentInfo = $ref(false)

const click = async (name, group, id) => {
    if (group === 'virtual') {
        currentComponent = { name, group, nextRunTime: '', onlyThisUsed: false, errTransfer: 1 }
        showComponentInfo = true;
    } else {
        let wfSequence = route.query.id || 0;
        const resData = await useRequest({ url: "/jobinfo/componentInfo", jobId: id, workflowId: wfSequence });
        if (resData && resData.status) {
            currentComponent = resData.data;
            currentComponent.sequence = id;
            currentComponent.wfSequence = wfSequence;
            showComponentInfo = true;
        }
    }
}

let commonInfo = $ref({ glueSource: "" })

watch(() => showComponentInfo, status => {
    useModalSize(status)
})

const validate = () => {
    return new Promise((resolve) => {
        save() ? resolve(true) : resolve(false)
    })
}

const fill = (data) => {
    commonInfo.glueSource = data.glueSource
}

const workflowRef = $ref(null)

let id = $ref(null)
let currentNodeId = $ref(null)
let lastDataBak = $ref({})
let bt_loading = $ref(false)
let tb_loading = $ref(false)
let DataAll = $ref({ 'edges': [], 'nodes': [] })
let workflowVisible = $ref(false)
let searchForm = $ref({
    jobDesc: '',
    jobGroup: 0,
    executorHandler: '',
    triggerStatus: -1,
    author: '',
    glueType: "",
    wf: route.query.id || 0
})
let currentPage = $ref(1)
let page_size = $ref(0)
let page_sizes = [10, 30, 50, 100, 200]
let total = $ref(0)
let iconMap = $ref({})
let tableData = $ref([])

const isNewWorkflow = $computed(() => {
    return !route.query.id;
})
const toolbar = $computed(() => {
    let tool = [{
        function: () => {
            getWorkflowInfo()
        }, icon: 'refresh'
    }]
    if (props.saveButton) {
        tool.push({
            function: () => {
                save(() => {
                    useElMessage.success("校验成功")
                })
            }, icon: 'Warning'
        })
    }
    return tool;
})

const emits = defineEmits(["npc"])

const getGlueType = (glueType) => {
    if (glueType.startsWith("GLUE")) {
        let type = glueType.split("_")[1];
        return type === "GROOVY" ? "java" : type.toLowerCase()
    } else {
        return glueType.toLowerCase()
    }
}

const openTask = (taskInfo) => {
    let url = '/task/' + taskInfo.taskType + '?id=' + taskInfo.id
    storeInstance.tagMenuStore.setTitle(taskInfo.name)
    router.push(url)
}
const getTaskData = async (params) => {
    tb_loading = true;
    bt_loading = true;
    const resData = await useRequest({ url: '/jobinfo/getPageData', ...params });
    //重置表数据
    tableData = []
    if (resData && resData.data) {
        tableData = resData.data;
        total = resData.totalRecord;
    }
    tableData.splice(0, 0, { jobDesc: "wait", glueType: "virtual", remark: "等待" })
    tb_loading = false;
    bt_loading = false;
}
const search = () => {
    getTaskData({
        ...searchForm, limit: page_size, page: 1
    });
    currentPage = 1;
}
const SizeChange = (val) => {
    getTaskData({
        ...searchForm, limit: val, page: currentPage
    });
    page_size = val;
}
const CurrentChange = (val) => {
    getTaskData({
        ...searchForm, limit: page_size, page: val
    });
    currentPage = val;
}
const addNodeFunction = () => {
    workflowVisible = true;
    currentNodeId = null;
}
const modifyJob = (scope) => {
    bt_loading = true;
    try {
        let name = scope.row.jobDesc;
        let sequence = (scope.row.id || new Date().getTime()).toString();
        let taskType = getGlueType(scope.row.glueType);
        let nodes = DataAll['nodes'];
        let edges = DataAll['edges'];
        let rej = false;

        nodes.forEach((e) => {
            if (e.id === sequence) {
                rej = true
            }
        });
        if (rej) {
            useElMessage.error('重复节点')
        } else {
            if (currentNodeId) {
                edges.forEach((e) => {
                    if (e.dst_node_id === currentNodeId) {
                        e.dst_node_id = sequence
                    } else if (e.src_node_id === currentNodeId) {
                        e.src_node_id = sequence
                    }
                });
                nodes.forEach((e) => {
                    if (e.id === currentNodeId) {
                        e.name = name;
                        e.id = sequence;
                        e.taskType = taskType;
                        e.iconClassName = iconMap[taskType];
                        e.iconStyle.background = 'orange'
                        if (e.taskType === "virtual") {
                            e.iconStyle.background = '#c0c4cc'
                        }
                        currentNodeId = sequence;
                    }
                });
            } else {
                let icon = iconMap[taskType];
                workflowRef.addNode({
                    id: sequence,
                    name: name,
                    taskType: taskType,
                    iconClassName: icon ? icon : "el-icon-check",
                    iconStyle: {
                        background: taskType !== 'virtual' ? "orange" : "#c0c4cc",
                    }
                })
            }
            workflowVisible = false
        }
    } finally {
        bt_loading = false;
    }
}
const updateWorkflow = (data, t) => {
    if (t === 'addNode' && data === 'name exists null,operation reject') {
        useElMessage.error('存在未命名节点')
    }
}
const editNodeDetails = (node) => {
    let nodes = DataAll['nodes'];
    nodes.forEach((e) => {
        if (e.id === node.id) {
            e.name = 'ModifyNode'
        }
    });
}
const focusInput = (id) => {
    useModalSize()
    currentNodeId = id;
    workflowVisible = true;
}
const close = () => {
    useModalSize(false)
    setTimeout(() => {
        currentNodeId = null;
    }, 300)
}
const save = (successCallback) => {
    let _nodes = DataAll.nodes;
    let _edges = [];

    DataAll.edges.forEach((e) => {
        _edges.push(e.dst_node_id);
        _edges.push(e.src_node_id)
    });

    let path_connect = false;
    _nodes.forEach((e) => {
        if (!isInArray(e.id, _edges)) {
            path_connect = true
        }
    });

    let rej = false;
    _nodes.forEach((e) => {
        if (!e.name) {
            rej = true
        }
    });

    if (rej) {
        useElMessage.error('工作流存在未命名节点')
    } else if (path_connect && !(DataAll.edges.length === 0 && DataAll.nodes.length === 1)) {
        useElMessage.error('工作流存在未连接节点')
    } else if (_nodes.length > 1) {
        if (successCallback) successCallback()
        return {
            workflow: DataAll,
            orig: lastDataBak,
            sequence: route.query.id,
        }
    } else {
        useElMessage.error('工作流至少需要存在两个节点')
    }
}
const getWorkflowInfo = async () => {
    id = route.query.id
    if (isNewWorkflow) {
        iconMap = { virtual: "el-icon-more" }
        return
    }
    const resData = await useRequest({ url: '/jobinfo/workflow', id: id });
    if (resData && resData.status) {
        if (!isNewWorkflow) {
            DataAll = resData.data.workflow;
        }
        lastDataBak = deepCopy(DataAll);//todo 保存副本,和服务器数据比对,一致则证明中途无修改
        iconMap = resData.data.iconMap;
    }
}

onMounted(() => {
    getWorkflowInfo();
    SizeChange(page_sizes[1]);
})
defineExpose({ validate, save, fill })
</script>

<style scoped lang="scss">
:deep(.el-dialog .el-dialog__body) {
    padding: 10px !important;
}

:deep(.el-dialog .el-dialog__header) {
    border-bottom: 1px solid #e4e7ec;
    padding: 20px 10px 10px
}

:deep(.el-dialog .el-dialog__footer) {
    padding: 5px 20px 10px;
    border-top: 1px solid #e4e7ec;
}

:deep(.el-dialog .el-dialog__body .el-form-item) {
    margin-bottom: 15px
}
</style>

<style>
.dag-page-dialog {
    width: var(--el-dialog-width);
    height: calc(100vh - 125px);
    padding: 10px 10px 0 10px !important;
    margin: var(--el-dialog-margin-top, 15vh) auto 65px;

    .el-dialog__body {
        padding: 0;
        height: 100%;
    }

    .table-with-pagination.el-table {
        height: calc(100% - var(--font-size)* 2 - 105px);
        background: transparent;
    }

    .el-dialog__header {
        padding: 10px;
    }
}

.fullscreen {
    overflow: hidden;
    width: 100vw;
    height: 100vh;
    position: relative;
    background: transparent url("@/assets/image/bg-sm.jpg") no-repeat 50%;
    background-size: cover;
}

.fullscreen-inner {
    background: rgba(255, 255, 255, .9);
}
</style>